{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configuration for Colab"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "IN_COLAB = 'google.colab' in sys.modules\n",
    "\n",
    "if IN_COLAB:\n",
    "    !apt-get install -y xvfb python-opengl > /dev/null 2>&1\n",
    "    !pip install gym pyvirtualdisplay > /dev/null 2>&1\n",
    "    !pip install JSAnimation==0.1\n",
    "    !pip install pyglet==1.3.2\n",
    "    \n",
    "    from pyvirtualdisplay import Display\n",
    "    \n",
    "    # Start virtual display\n",
    "    dis = Display(visible=0, size=(400, 400))\n",
    "    dis.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 06. DDPGfD\n",
    "\n",
    "[M. Vecerik et al., \"Leveraging Demonstrations for Deep Reinforcement Learning on Robotics Problems with Sparse Rewards.\"arXiv preprint arXiv:1707.08817, 2017](https://arxiv.org/pdf/1707.08817.pdf)\n",
    "\n",
    "ReinforcementLearning (RL) offers, in principle, a method to learn such policies from exploration, but the amount of actual exploration required has prohibited its use in real applications. In this paper the authors address this challenge by combining the demonstration and RL paradigms into a single framework which uses demonstrations to guide a deep-RL algorithm. \n",
    "\n",
    "The central contribution of this paper is to show that off-policy replay-memory-based RL (e.g. DDPG) is a natural vehicle for injecting demonstration data into sparse-reward tasks and that it obviates the need for reward-shaping. \n",
    "\n",
    "The algorithms called DDPG from Demonstration (*DDPGfD*) modifies DDPG to take advantage of demonstrations.\n",
    "\n",
    "### DDPG\n",
    "For learning in high-dimentional and continous action spaces, the authors of DDPG combine the actor-critic approach with insights from the success of DQN. Deep DPG(DDPG) is based on the deterministic policy gradient(DPG) algorithm ([Silver et al., 2014](http://proceedings.mlr.press/v32/silver14.pdf)). Please see *03.DDPG.ipynb* for detailed description of DDPG.\n",
    "\n",
    "### Prioritized Experience Replay (PER)\n",
    "Prioritized experience replay modifies the agent to sample more important transitions from its replay buffer more frequently.\n",
    "\n",
    "The probability of sampling a particular transition is proportional to its priority,\n",
    "$$\n",
    "P(i) = \\frac{p_i^{\\alpha}}{\\sum_k p_k^{\\alpha}}\n",
    "$$\n",
    ", where $p_i$ the priority of the transition. The priority is commonly to use the magnitude of a transition’s TD error.\n",
    "\n",
    "DDPGfD uses \n",
    "$$\n",
    "p_i = \\delta^{2}_{i} + \\lambda_3 |\\nabla_a Q(s_i, a_i|\\theta^Q)|^2 + \\epsilon + \\epsilon_D,\n",
    "$$\n",
    "- $\\delta_i$ is the last TD error calculated for this transition. The second term represents the loss applied to the actor.\n",
    "- $\\epsilon$ is a small positive constant to ensure all transitions are sampled with some probability.\n",
    "- $\\epsilon_D$ is a positive constant for demonstration transitions to increase their probability of getting sampled.\n",
    "- $\\lambda_3$ is used to weight the contributions.\n",
    "\n",
    "One more. Let's recall one of the main ideas of DQN. To remove correlation of observations, it uses uniformly random sampling from the replay buffer. Prioritized replay introduces bias because it doesn't sample experiences uniformly at random due to the sampling proportion correspoding to TD-error. We can correct this bias by using importance-sampling (IS) weights\n",
    "\n",
    "$$\n",
    "w_i = \\big( \\frac{1}{N} \\cdot \\frac{1}{P(i)} \\big)^\\beta\n",
    "$$\n",
    "\n",
    "that fully compensates for the non-uniform probabilities $P(i)$ if $\\beta = 1$. These weights can be folded into the Q-learning update by using $w_i\\delta_i$ instead of $\\delta_i$.\n",
    "\n",
    "For details, refer to the PER paper ([T. Schaul et al., 2015.](https://arxiv.org/pdf/1511.05952.pdf))\n",
    "\n",
    "### A mix of 1-step and n-step returns\n",
    "A modification for the sparse reward case is to use a mix of 1-step and n-step returns when updating the critic function. Incorporating *n-step returns* helps propagate the Q-values along the trajectories.\n",
    "\n",
    "The n-step return has the following form:\n",
    "$$\n",
    "R_n = \\sum^{n-1}_{i=0} \\gamma^i r_i + \\gamma^n Q(s'_{n-1}, \\pi(s'_{n-1}; \\theta^{Q'}))\n",
    "$$\n",
    "\n",
    "The loss corresponding to this particular rollout is then:\n",
    "$$\n",
    "L_n(\\theta^Q) = \\frac{1}{2} (R_n - Q(s, \\pi(s) | \\theta^Q))^2\n",
    "$$\n",
    "\n",
    "### Loss function\n",
    "The loss function is combined the above mentioned losses. Additionally *L2 regularization* on the parameters of the actor and the critic networks are added to stabilize the final learning performance. Two parameters called $\\lambda_1$, $\\lambda_2$ are used to weight the contributions.\n",
    "\n",
    "$$\n",
    "L_{Critic}(\\theta ^ Q) = L_1(\\theta^Q) + \\lambda_1 L_n(\\theta^Q) + \\lambda_2 L^{C}_{reg} (\\theta^Q)   \\\\\n",
    "$$\n",
    "$$\n",
    "\\nabla_{\\theta^{\\pi}} L_{Actor}(\\theta^\\pi) = - \\nabla_{\\theta^{\\pi}} J(\\theta^\\pi) + \\lambda_2 L^{A}_{reg} (\\theta^\\pi)\n",
    "$$\n",
    "\n",
    "### Pretrain\n",
    "We make use of the demonstration data to pre-train the agent so that it can perform well in the task from the start of learning, and then continue improving from its own self-generated data.\n",
    "\n",
    "Reference: \n",
    "- [Pseudo code of DDPGfD paper](https://arxiv.org/pdf/1707.08817.pdf)\n",
    "- [DQfD](https://arxiv.org/pdf/1704.03732)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Import modules"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import copy\n",
    "import random\n",
    "from collections import deque\n",
    "from typing import Deque, Dict, List, Tuple\n",
    "\n",
    "import gym\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "\n",
    "from IPython.display import clear_output\n",
    "\n",
    "if IN_COLAB and not os.path.exists(\"segment_tree.py\") and not os.path.exists(\"demo.pkl\"):\n",
    "    # download segment tree module\n",
    "    !wget https://raw.githubusercontent.com/mrsyee/pg-is-all-you-need/master/segment_tree.py\n",
    "    # download demo.pkl\n",
    "    !wget https://raw.githubusercontent.com/mrsyee/pg-is-all-you-need/master/demo.pkl\n",
    "        \n",
    "from segment_tree import MinSegmentTree, SumSegmentTree"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set random seed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "if torch.backends.cudnn.enabled:\n",
    "    torch.backends.cudnn.benchmark = False\n",
    "    torch.backends.cudnn.deterministic = True\n",
    "\n",
    "seed = 777\n",
    "torch.manual_seed(seed)\n",
    "np.random.seed(seed)\n",
    "random.seed(seed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Replay buffer for N-step learning with demonstration\n",
    "\n",
    "There are a little bit changes in Replay buffer for N-step learning with demonstration.\n",
    "\n",
    "First, we use `deque` to store the most recent n-step transitions.\n",
    "\n",
    "```python\n",
    "    self.n_step_buffer = deque(maxlen=n_step)\n",
    "```\n",
    "\n",
    "You can see it doesn't actually store a transition in the buffer, unless `n_step_buffer` is full.\n",
    "\n",
    "```\n",
    "    # in store method\n",
    "    if len(self.n_step_buffer) < self.n_step:\n",
    "        return ()\n",
    "```\n",
    "\n",
    "When the length of `n_step_buffer` becomes equal to N, it eventually stores the N-step transition, which is calculated by `get_n_step_info` method (reference `util.py`). Furthermore, there are additional implementations for saving loaded demos. (Please see *03.DDPG.ipynb* for detailed description of the basic replay buffer.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ReplayBuffer:\n",
    "    \"\"\"A numpy replay buffer with demonstrations.\"\"\"\n",
    "\n",
    "    def __init__(\n",
    "        self, \n",
    "        obs_dim: int, \n",
    "        size: int, \n",
    "        batch_size: int = 32, \n",
    "        gamma: float = 0.99,\n",
    "        demo: list = None,\n",
    "        n_step: int = 1, \n",
    "    ):\n",
    "        \"\"\"Initialize.\"\"\"\n",
    "        self.obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.next_obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.acts_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.rews_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.done_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.max_size, self.batch_size = size, batch_size\n",
    "        self.ptr, self.size = 0, 0\n",
    "        \n",
    "        # for N-step Learning\n",
    "        self.n_step_buffer = deque(maxlen=n_step)\n",
    "        self.n_step = n_step\n",
    "        self.gamma = gamma\n",
    "        \n",
    "        # for demonstration\n",
    "        self.demo_size = len(demo) if demo else 0\n",
    "        self.demo = demo\n",
    "        \n",
    "        if self.demo:\n",
    "            self.ptr += self.demo_size\n",
    "            self.size += self.demo_size\n",
    "            for ptr, d in enumerate(self.demo):\n",
    "                state, action, reward, next_state, done = d\n",
    "                self.obs_buf[ptr] = state\n",
    "                self.acts_buf[ptr] = np.array(action)\n",
    "                self.rews_buf[ptr] = reward\n",
    "                self.next_obs_buf[ptr] = next_state\n",
    "                self.done_buf[ptr] = done\n",
    "\n",
    "    def store(\n",
    "        self,\n",
    "        obs: np.ndarray,\n",
    "        act: np.ndarray, \n",
    "        rew: float, \n",
    "        next_obs: np.ndarray, \n",
    "        done: bool,\n",
    "    ) -> Tuple[np.ndarray, np.ndarray, float, np.ndarray, bool]:\n",
    "        \"\"\"Store the transition in buffer.\"\"\"\n",
    "        transition = (obs, act, rew, next_obs, done)\n",
    "        self.n_step_buffer.append(transition)\n",
    "        \n",
    "        # single step transition is not ready\n",
    "        if len(self.n_step_buffer) < self.n_step:\n",
    "            return ()\n",
    "        \n",
    "        # make a n-step transition\n",
    "        rew, next_obs, done = self._get_n_step_info()\n",
    "        obs, act = self.n_step_buffer[0][:2]\n",
    "        \n",
    "        self.obs_buf[self.ptr] = obs\n",
    "        self.next_obs_buf[self.ptr] = next_obs\n",
    "        self.acts_buf[self.ptr] = act\n",
    "        self.rews_buf[self.ptr] = rew\n",
    "        self.done_buf[self.ptr] = done\n",
    "        \n",
    "        self.ptr += 1\n",
    "        self.ptr = self.demo_size if self.ptr % self.max_size == 0 else self.ptr\n",
    "        self.size = min(self.size + 1, self.max_size)\n",
    "        \n",
    "        return self.n_step_buffer[0]\n",
    "\n",
    "    def sample_batch(self, indices: List[int] = None) -> Dict[str, np.ndarray]:\n",
    "        \"\"\"Randomly sample a batch of experiences from memory.\"\"\"\n",
    "        assert len(self) >= self.batch_size\n",
    "        \n",
    "        if indices is None:\n",
    "            indices = np.random.choice(\n",
    "                len(self), size=self.batch_size, replace=False\n",
    "            )\n",
    "            \n",
    "        return dict(\n",
    "            obs=self.obs_buf[indices],\n",
    "            next_obs=self.next_obs_buf[indices],\n",
    "            acts=self.acts_buf[indices],\n",
    "            rews=self.rews_buf[indices],\n",
    "            done=self.done_buf[indices],\n",
    "            # for N-step learning\n",
    "            indices=indices,\n",
    "        )\n",
    "    \n",
    "    def _get_n_step_info(self) -> Tuple[np.int64, np.ndarray, bool]:\n",
    "        \"\"\"Return n step rew, next_obs, and done.\"\"\"\n",
    "        # info of the last transition\n",
    "        rew, next_obs, done = self.n_step_buffer[-1][-3:]\n",
    "\n",
    "        for transition in reversed(list(self.n_step_buffer)[:-1]):\n",
    "            r, n_o, d = transition[-3:]\n",
    "\n",
    "            rew = r + self.gamma * rew * (1 - d)\n",
    "            next_obs, done = (n_o, d) if d else (next_obs, done)\n",
    "\n",
    "        return rew, next_obs, done\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self.size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Prioritized replay Buffer with demonstration\n",
    "\n",
    "The key concept of PER's implementation is *Segment Tree*. It efficiently stores and samples transitions while managing the priorities of them (reference `segment_tree.py`). We recommend you understand how it works before you move on. Here are references for you:\n",
    "\n",
    "- In Korean: https://mrsyee.github.io/rl/2019/01/25/PER-sumtree/\n",
    "- In English: https://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/\n",
    "\n",
    "In addtion, `epsilon_d` is a positive constant for demonstration transitions to increase their probability of getting sampled."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class PrioritizedReplayBuffer(ReplayBuffer):\n",
    "    \"\"\"Prioritized Replay buffer with demonstrations.\"\"\"\n",
    "    \n",
    "    def __init__(\n",
    "        self, \n",
    "        obs_dim: int,\n",
    "        size: int, \n",
    "        batch_size: int = 32, \n",
    "        gamma: float = 0.99,\n",
    "        alpha: float = 0.6,\n",
    "        epsilon_d: float = 1.0,\n",
    "        demo: list = None,\n",
    "    ):\n",
    "        \"\"\"Initialize.\"\"\"\n",
    "        assert alpha >= 0\n",
    "        \n",
    "        super(PrioritizedReplayBuffer, self).__init__(\n",
    "            obs_dim, size, batch_size, gamma, demo, n_step=1 \n",
    "        )\n",
    "        self.max_priority, self.tree_ptr = 1.0, 0\n",
    "        self.alpha = alpha\n",
    "        self.epsilon_d = epsilon_d\n",
    "        \n",
    "        # capacity must be positive and a power of 2.\n",
    "        tree_capacity = 1\n",
    "        while tree_capacity < self.max_size:\n",
    "            tree_capacity *= 2\n",
    "\n",
    "        self.sum_tree = SumSegmentTree(tree_capacity)\n",
    "        self.min_tree = MinSegmentTree(tree_capacity)\n",
    "        \n",
    "        # for init priority of demo\n",
    "        self.tree_ptr = self.demo_size\n",
    "        for i in range(self.demo_size):\n",
    "            self.sum_tree[i] = self.max_priority ** self.alpha\n",
    "            self.min_tree[i] = self.max_priority ** self.alpha\n",
    "        \n",
    "    def store(\n",
    "        self, \n",
    "        obs: np.ndarray, \n",
    "        act: int, \n",
    "        rew: float, \n",
    "        next_obs: np.ndarray, \n",
    "        done: bool\n",
    "    ):\n",
    "        \"\"\"Store experience and priority.\"\"\"\n",
    "        transition = super().store(obs, act, rew, next_obs, done)\n",
    "        \n",
    "        if transition:\n",
    "            self.sum_tree[self.tree_ptr] = self.max_priority ** self.alpha\n",
    "            self.min_tree[self.tree_ptr] = self.max_priority ** self.alpha\n",
    "\n",
    "            self.tree_ptr += 1\n",
    "            if self.tree_ptr % self.max_size == 0:\n",
    "                self.tree_ptr = self.demo_size\n",
    "            \n",
    "        return transition\n",
    "\n",
    "    def sample_batch(self, beta: float = 0.4) -> Dict[str, np.ndarray]:\n",
    "        \"\"\"Sample a batch of experiences.\"\"\"\n",
    "        assert len(self) >= self.batch_size\n",
    "        assert beta > 0\n",
    "        \n",
    "        indices = self._sample_proportional()\n",
    "        \n",
    "        obs = self.obs_buf[indices]\n",
    "        next_obs = self.next_obs_buf[indices]\n",
    "        acts = self.acts_buf[indices]\n",
    "        rews = self.rews_buf[indices]\n",
    "        done = self.done_buf[indices]\n",
    "        weights = np.array([self._calculate_weight(i, beta) for i in indices])\n",
    "        epsilon_d = np.array(\n",
    "            [self.epsilon_d if i < self.demo_size else 0.0 for i in indices]\n",
    "        )\n",
    "        \n",
    "        return dict(\n",
    "            obs=obs,\n",
    "            next_obs=next_obs,\n",
    "            acts=acts,\n",
    "            rews=rews,\n",
    "            done=done,\n",
    "            weights=weights,\n",
    "            epsilon_d=epsilon_d,\n",
    "            indices=indices,\n",
    "        )\n",
    "        \n",
    "    def update_priorities(self, indices: List[int], priorities: np.ndarray):\n",
    "        \"\"\"Update priorities of sampled transitions.\"\"\"\n",
    "        assert len(indices) == len(priorities)\n",
    "\n",
    "        for idx, priority in zip(indices, priorities):\n",
    "            assert priority > 0\n",
    "            assert 0 <= idx < len(self)\n",
    "\n",
    "            self.sum_tree[idx] = priority ** self.alpha\n",
    "            self.min_tree[idx] = priority ** self.alpha\n",
    "\n",
    "            self.max_priority = max(self.max_priority, priority)\n",
    "            \n",
    "    def _sample_proportional(self) -> List[int]:\n",
    "        \"\"\"Sample indices based on proportions.\"\"\"\n",
    "        indices = []\n",
    "        p_total = self.sum_tree.sum(0, len(self) - 1)\n",
    "        segment = p_total / self.batch_size\n",
    "        \n",
    "        for i in range(self.batch_size):\n",
    "            a = segment * i\n",
    "            b = segment * (i + 1)\n",
    "            upperbound = random.uniform(a, b)\n",
    "            idx = self.sum_tree.retrieve(upperbound)\n",
    "            indices.append(idx)\n",
    "            \n",
    "        return indices\n",
    "    \n",
    "    def _calculate_weight(self, idx: int, beta: float):\n",
    "        \"\"\"Calculate the weight of the experience at idx.\"\"\"\n",
    "        # get max weight\n",
    "        p_min = self.min_tree.min() / self.sum_tree.sum()\n",
    "        max_weight = (p_min * len(self)) ** (-beta)\n",
    "        \n",
    "        # calculate weights\n",
    "        p_sample = self.sum_tree[idx] / self.sum_tree.sum()\n",
    "        weight = (p_sample * len(self)) ** (-beta)\n",
    "        weight = weight / max_weight\n",
    "        \n",
    "        return weight"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## OU Noise\n",
    "*Ornstein-Uhlenbeck* process generates temporally correlated exploration, and it effectively copes with physical control problems of inertia.\n",
    "\n",
    "$$\n",
    "dx_t = \\theta(\\mu - x_t) dt + \\sigma dW_t\n",
    "$$\n",
    "\n",
    "Reference: \n",
    "- [Udacity github](https://github.com/udacity/deep-reinforcement-learning/blob/master/ddpg-pendulum/ddpg_agent.py)\n",
    "- [Wiki](https://en.wikipedia.org/wiki/Ornstein%E2%80%93Uhlenbeck_process)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class OUNoise:\n",
    "    \"\"\"Ornstein-Uhlenbeck process.\n",
    "    Taken from Udacity deep-reinforcement-learning github repository:\n",
    "    https://github.com/udacity/deep-reinforcement-learning/blob/master/\n",
    "    ddpg-pendulum/ddpg_agent.py\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(\n",
    "        self, \n",
    "        size: int, \n",
    "        mu: float = 0.0, \n",
    "        theta: float = 0.15, \n",
    "        sigma: float = 0.2,\n",
    "    ):\n",
    "        \"\"\"Initialize parameters and noise process.\"\"\"\n",
    "        self.state = np.float64(0.0)\n",
    "        self.mu = mu * np.ones(size)\n",
    "        self.theta = theta\n",
    "        self.sigma = sigma\n",
    "        self.reset()\n",
    "\n",
    "    def reset(self):\n",
    "        \"\"\"Reset the internal state (= noise) to mean (mu).\"\"\"\n",
    "        self.state = copy.copy(self.mu)\n",
    "\n",
    "    def sample(self) -> np.ndarray:\n",
    "        \"\"\"Update internal state and return it as a noise sample.\"\"\"\n",
    "        x = self.state\n",
    "        dx = self.theta * (self.mu - x) + self.sigma * np.array(\n",
    "            [random.random() for _ in range(len(x))]\n",
    "        )\n",
    "        self.state = x + dx\n",
    "        return self.state"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Network\n",
    "We are going to use two separated networks for actor and critic. The actor network has three fully connected layers and three non-linearity functions, *ReLU* for hidden layers and *tanh* for the output layer. On the other hand, the critic network has three fully connected layers, but it used two activation functions for hidden layers *ReLU*. Plus, its input sizes of critic network are sum of state sizes and action sizes. One thing to note is that we initialize the final layer's weights and biases so that they are *uniformly distributed.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Actor(nn.Module):\n",
    "    def __init__(\n",
    "        self, \n",
    "        in_dim: int, \n",
    "        out_dim: int,\n",
    "        init_w: float = 3e-3,\n",
    "    ):\n",
    "        \"\"\"Initialize.\"\"\"\n",
    "        super(Actor, self).__init__()\n",
    "        \n",
    "        self.hidden1 = nn.Linear(in_dim, 128)\n",
    "        self.hidden2 = nn.Linear(128, 128)\n",
    "        self.out = nn.Linear(128, out_dim)\n",
    "        \n",
    "        self.out.weight.data.uniform_(-init_w, init_w)\n",
    "        self.out.bias.data.uniform_(-init_w, init_w)\n",
    "\n",
    "    def forward(self, state: torch.Tensor) -> torch.Tensor:\n",
    "        \"\"\"Forward method implementation.\"\"\"\n",
    "        x = F.relu(self.hidden1(state))\n",
    "        x = F.relu(self.hidden2(x))\n",
    "        action = self.out(x).tanh()\n",
    "        \n",
    "        return action\n",
    "    \n",
    "    \n",
    "class Critic(nn.Module):\n",
    "    def __init__(\n",
    "        self, \n",
    "        in_dim: int, \n",
    "        init_w: float = 3e-3,\n",
    "    ):\n",
    "        \"\"\"Initialize.\"\"\"\n",
    "        super(Critic, self).__init__()\n",
    "        \n",
    "        self.hidden1 = nn.Linear(in_dim, 128)\n",
    "        self.hidden2 = nn.Linear(128, 128)\n",
    "        self.out = nn.Linear(128, 1)\n",
    "        \n",
    "        self.out.weight.data.uniform_(-init_w, init_w)\n",
    "        self.out.bias.data.uniform_(-init_w, init_w)\n",
    "\n",
    "    def forward(\n",
    "        self, state: torch.Tensor, action: torch.Tensor\n",
    "    ) -> torch.Tensor:\n",
    "        \"\"\"Forward method implementation.\"\"\"\n",
    "        x = torch.cat((state, action), dim=-1)\n",
    "        x = F.relu(self.hidden1(x))\n",
    "        x = F.relu(self.hidden2(x))\n",
    "        value = self.out(x)\n",
    "        \n",
    "        return value"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## DDPGfD Agent\n",
    "Here is a summary of DDPGfDAgent class.\n",
    "\n",
    "| Method           | Note                                                 |\n",
    "|---               |---                                                  |\n",
    "|select_action     | select an action from the input state.               |\n",
    "|step              | take an action and return the response of the env.   |\n",
    "|update_model      | update the model by gradient descent.                |\n",
    "|train             | train the agent during num_frames.                   |\n",
    "|test              | test the agent (1 episode).                          |\n",
    "|\\_pretrain        |pretraining steps.|\n",
    "|\\_get_critic_loss   | return element-wise critic loss.                     |\n",
    "|\\_target_soft_update| soft update from the local model to the target model.|\n",
    "|\\_get_n_step_info_from_demo | return 1 step and n step demos. |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DDPGfDAgent:\n",
    "    \"\"\"DDPGfDAgent interacting with environment.\n",
    "    \n",
    "    Attribute:\n",
    "        env (gym.Env): openAI Gym environment\n",
    "        actor (nn.Module): target actor model to select actions\n",
    "        actor_target (nn.Module): actor model to predict next actions\n",
    "        actor_optimizer (Optimizer): optimizer for training actor\n",
    "        critic (nn.Module): critic model to predict state values\n",
    "        critic_target (nn.Module): target critic model to predict state values\n",
    "        critic_optimizer (Optimizer): optimizer for training critic\n",
    "        demo (list): demonstration\n",
    "        memory (ReplayBuffer): replay memory to store transitions\n",
    "        batch_size (int): batch size for sampling\n",
    "        gamma (float): discount factor\n",
    "        tau (float): parameter for soft target update\n",
    "        initial_random_steps (int): initial random action steps\n",
    "        pretrain_step (int): the number of step for pre-training\n",
    "        n_step (int): the number of multi step\n",
    "        use_n_step (bool): whether to use n_step memory\n",
    "        prior_eps (float): guarantees every transitions can be sampled\n",
    "        lambda1 (float): n-step return weight\n",
    "        lambda2 (float): l2 regularization weight\n",
    "        lambda3 (float): actor loss contribution of prior weight\n",
    "        noise (OUNoise): noise generator for exploration\n",
    "        device (torch.device): cpu / gpu\n",
    "        transition (list): temporory storage for the recent transition\n",
    "        total_step (int): total step numbers\n",
    "        is_test (bool): flag to show the current mode (train / test)\n",
    "    \"\"\"\n",
    "    def __init__(\n",
    "        self,\n",
    "        env: gym.Env,\n",
    "        memory_size: int,\n",
    "        batch_size: int,\n",
    "        ou_noise_theta: float,\n",
    "        ou_noise_sigma: float,\n",
    "        demo: list,\n",
    "        pretrain_step: int,\n",
    "        gamma: float = 0.99,\n",
    "        tau: float = 5e-3,\n",
    "        initial_random_steps: int = 1e4,\n",
    "        # PER parameters\n",
    "        alpha: float = 0.3,\n",
    "        beta: float = 1.0,\n",
    "        prior_eps: float = 1e-6,\n",
    "        # N-step Learning\n",
    "        n_step: int = 3,\n",
    "        # loss parameters\n",
    "        lambda1: float = 1.0, # N-step return weight\n",
    "        lambda2: float = 1e-4, # l2 regularization weight\n",
    "        lambda3: float = 1.0, # actor loss contribution of prior weight\n",
    "    ):\n",
    "        \"\"\"Initialize.\"\"\"\n",
    "        obs_dim = env.observation_space.shape[0]\n",
    "        action_dim = env.action_space.shape[0]\n",
    "\n",
    "        self.env = env\n",
    "        self.batch_size = batch_size\n",
    "        self.pretrain_step = pretrain_step\n",
    "        self.gamma = gamma\n",
    "        self.tau = tau\n",
    "        self.initial_random_steps = initial_random_steps\n",
    "        self.lambda1 = lambda1\n",
    "        self.lambda3 = lambda3\n",
    "        \n",
    "        self.demo = demo\n",
    "        demos_1_step, demos_n_step = [], []\n",
    "        if self.demo:\n",
    "            demos_1_step, demos_n_step = self._get_n_step_info_from_demo(\n",
    "                demo, n_step\n",
    "            )\n",
    "        \n",
    "        # PER\n",
    "        # memory for 1-step Learning\n",
    "        self.beta = beta\n",
    "        self.prior_eps = prior_eps\n",
    "        self.memory = PrioritizedReplayBuffer(\n",
    "            obs_dim, memory_size, batch_size, gamma, alpha, demo=demos_1_step\n",
    "        )\n",
    "        \n",
    "        # memory for N-step Learning\n",
    "        self.use_n_step = True if n_step > 1 else False\n",
    "        if self.use_n_step:\n",
    "            self.n_step = n_step\n",
    "            self.memory_n = ReplayBuffer(\n",
    "                obs_dim, \n",
    "                memory_size, \n",
    "                batch_size, \n",
    "                gamma, \n",
    "                demos_n_step, \n",
    "                self.n_step\n",
    "            )\n",
    "                \n",
    "        # noise\n",
    "        self.noise = OUNoise(\n",
    "            action_dim,\n",
    "            theta=ou_noise_theta,\n",
    "            sigma=ou_noise_sigma,\n",
    "        )\n",
    "\n",
    "        # device: cpu / gpu\n",
    "        self.device = torch.device(\n",
    "            \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "        )\n",
    "        print(self.device)\n",
    "\n",
    "        # networks\n",
    "        self.actor = Actor(obs_dim, action_dim).to(self.device)\n",
    "        self.actor_target = Actor(obs_dim, action_dim).to(self.device)\n",
    "        self.actor_target.load_state_dict(self.actor.state_dict())\n",
    "        \n",
    "        self.critic = Critic(obs_dim + action_dim).to(self.device)\n",
    "        self.critic_target = Critic(obs_dim + action_dim).to(self.device)\n",
    "        self.critic_target.load_state_dict(self.critic.state_dict())\n",
    "\n",
    "        # optimizer\n",
    "        self.actor_optimizer = optim.Adam(\n",
    "            self.actor.parameters(),\n",
    "            lr=3e-4,\n",
    "            weight_decay=lambda2,\n",
    "        )\n",
    "        self.critic_optimizer = optim.Adam(\n",
    "            self.critic.parameters(),\n",
    "            lr=1e-3,\n",
    "            weight_decay=lambda2,\n",
    "        )\n",
    "        \n",
    "        # transition to store in memory\n",
    "        self.transition = list()\n",
    "        \n",
    "        # total steps count\n",
    "        self.total_step = 0\n",
    "\n",
    "        # mode: train / test\n",
    "        self.is_test = False\n",
    "    \n",
    "    def select_action(self, state: np.ndarray) -> np.ndarray:\n",
    "        \"\"\"Select an action from the input state.\"\"\"\n",
    "        # if initial random action should be conducted\n",
    "        if self.total_step < self.initial_random_steps and not self.is_test:\n",
    "            selected_action = self.env.action_space.sample()\n",
    "        else:\n",
    "            selected_action = self.actor(\n",
    "                torch.FloatTensor(state).to(self.device)\n",
    "            ).detach().cpu().numpy()\n",
    "        \n",
    "        # add noise for exploration during training\n",
    "        if not self.is_test:\n",
    "            noise = self.noise.sample()\n",
    "            selected_action = np.clip(selected_action + noise, -1.0, 1.0)\n",
    "        \n",
    "        self.transition = [state, selected_action]\n",
    "        \n",
    "        return selected_action\n",
    "    \n",
    "    def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool]:\n",
    "        \"\"\"Take an action and return the response of the env.\"\"\"\n",
    "        next_state, reward, done, _ = self.env.step(action)\n",
    "        \n",
    "        if not self.is_test:\n",
    "            self.transition += [reward, next_state, done]\n",
    "            \n",
    "            # N-step transition\n",
    "            transition = self.transition\n",
    "            if self.use_n_step:\n",
    "                transition = self.memory_n.store(*self.transition)\n",
    "\n",
    "            # add a single step transition\n",
    "            if transition:\n",
    "                self.memory.store(*transition)\n",
    "    \n",
    "        return next_state, reward, done\n",
    "    \n",
    "    def update_model(self) -> Tuple[torch.Tensor, ...]:\n",
    "        \"\"\"Update the model by gradient descent.\"\"\"\n",
    "        device = self.device  # for shortening the following lines\n",
    "        \n",
    "        samples = self.memory.sample_batch(self.beta)        \n",
    "        state = torch.FloatTensor(samples[\"obs\"]).to(device)\n",
    "        action = torch.FloatTensor(samples[\"acts\"].reshape(-1, 1)).to(device)\n",
    "\n",
    "        weights = torch.FloatTensor(\n",
    "            samples[\"weights\"].reshape(-1, 1)\n",
    "        ).to(device)\n",
    "        epsilon_d = samples[\"epsilon_d\"]\n",
    "        indices = samples[\"indices\"]\n",
    "        \n",
    "        # train critic\n",
    "        # 1-step loss\n",
    "        critic_loss_element_wise = self._get_critic_loss(samples, self.gamma)\n",
    "        critic_loss = torch.mean(critic_loss_element_wise * weights)\n",
    "        \n",
    "        # n-step loss\n",
    "        if self.use_n_step:\n",
    "            samples_n = self.memory_n.sample_batch(indices)\n",
    "            n_gamma = self.gamma ** self.n_step\n",
    "            critic_loss_n_element_wise = self._get_critic_loss(\n",
    "                samples_n, n_gamma\n",
    "            )\n",
    "            \n",
    "            # to update loss and priorities\n",
    "            critic_loss_element_wise += (\n",
    "                critic_loss_n_element_wise * self.lambda1\n",
    "            )\n",
    "            critic_loss = torch.mean(critic_loss_element_wise * weights) \n",
    "        \n",
    "        self.critic_optimizer.zero_grad()\n",
    "        critic_loss.backward()\n",
    "        self.critic_optimizer.step()\n",
    "                \n",
    "        # train actor\n",
    "        actor_loss_element_wise = -self.critic(state, self.actor(state))\n",
    "        actor_loss = torch.mean(actor_loss_element_wise * weights)\n",
    "        \n",
    "        self.actor_optimizer.zero_grad()\n",
    "        actor_loss.backward()\n",
    "        self.actor_optimizer.step()\n",
    "        \n",
    "        # target update\n",
    "        self._target_soft_update()\n",
    "        \n",
    "        # PER: update priorities\n",
    "        new_priorities = critic_loss_element_wise\n",
    "        new_priorities += self.lambda3 * actor_loss_element_wise.pow(2)\n",
    "        new_priorities += self.prior_eps\n",
    "        new_priorities = new_priorities.data.cpu().numpy().squeeze()\n",
    "        new_priorities += epsilon_d\n",
    "        self.memory.update_priorities(indices, new_priorities)\n",
    "        \n",
    "        # check the number of sampling demos\n",
    "        demo_idxs = np.where(epsilon_d != 0.0)\n",
    "        n_demo = demo_idxs[0].size\n",
    "        \n",
    "        return actor_loss.data, critic_loss.data, n_demo\n",
    "    \n",
    "    def _pretrain(self) -> Tuple[List[torch.Tensor], List[torch.Tensor]]:\n",
    "        \"\"\"Pretraining steps.\"\"\"\n",
    "        actor_losses = []\n",
    "        critic_losses = []\n",
    "        print(\"Pre-Train %d step.\" % self.pretrain_step)\n",
    "        for _ in range(1, self.pretrain_step + 1):\n",
    "            actor_loss, critic_loss, _ = self.update_model()\n",
    "            actor_losses.append(actor_loss.data)\n",
    "            critic_losses.append(critic_loss.data)\n",
    "        print(\"Pre-Train Complete!\\n\")\n",
    "        return actor_losses, critic_losses\n",
    "    \n",
    "    def train(self, num_frames: int, plotting_interval: int = 200):\n",
    "        \"\"\"Train the agent.\"\"\"\n",
    "        self.is_test = False\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        actor_losses, critic_losses, n_demo_list, scores = [], [], [], []\n",
    "        score = 0\n",
    "        \n",
    "        if self.demo:\n",
    "            output = self._pretrain()\n",
    "            actor_losses.extend(output[0])\n",
    "            critic_losses.extend(output[1])\n",
    "        \n",
    "        for self.total_step in range(1, num_frames + 1):\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "            \n",
    "            # PER: increase beta\n",
    "            fraction = min(self.total_step / num_frames, 1.0)\n",
    "            self.beta = self.beta + fraction * (1.0 - self.beta)\n",
    "\n",
    "            # if episode ends\n",
    "            if done:         \n",
    "                state = env.reset()\n",
    "                scores.append(score)\n",
    "                score = 0\n",
    "\n",
    "            # if training is ready\n",
    "            if (\n",
    "                len(self.memory) >= self.batch_size \n",
    "                and self.total_step > self.initial_random_steps\n",
    "            ):\n",
    "                actor_loss, critic_loss, n_demo = self.update_model()\n",
    "                actor_losses.append(actor_loss)\n",
    "                critic_losses.append(critic_loss)\n",
    "                n_demo_list.append(n_demo)\n",
    "            \n",
    "            # plotting\n",
    "            if self.total_step % plotting_interval == 0:\n",
    "                self._plot(\n",
    "                    self.total_step, \n",
    "                    scores, \n",
    "                    actor_losses, \n",
    "                    critic_losses,\n",
    "                    n_demo_list,\n",
    "                )\n",
    "                \n",
    "        self.env.close()\n",
    "        \n",
    "    def test(self):\n",
    "        \"\"\"Test the agent.\"\"\"\n",
    "        self.is_test = True\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        done = False\n",
    "        score = 0\n",
    "        \n",
    "        frames = []\n",
    "        while not done:\n",
    "            frames.append(self.env.render(mode=\"rgb_array\"))\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "        \n",
    "        print(\"score: \", score)\n",
    "        self.env.close()\n",
    "        \n",
    "        return frames\n",
    "    \n",
    "    def _get_critic_loss(\n",
    "        self, samples: Dict[str, np.ndarray], gamma: float\n",
    "    ) -> torch.Tensor:\n",
    "        \"\"\"Return element-wise critic loss.\"\"\"\n",
    "        device = self.device  # for shortening the following lines\n",
    "        \n",
    "        state = torch.FloatTensor(samples[\"obs\"]).to(device)\n",
    "        next_state = torch.FloatTensor(samples[\"next_obs\"]).to(device)\n",
    "        action = torch.FloatTensor(samples[\"acts\"].reshape(-1, 1)).to(device)\n",
    "        reward = torch.FloatTensor(samples[\"rews\"].reshape(-1, 1)).to(device)\n",
    "        done = torch.FloatTensor(samples[\"done\"].reshape(-1, 1)).to(device)\n",
    "        \n",
    "        masks = 1 - done\n",
    "        next_action = self.actor_target(next_state)\n",
    "        next_value = self.critic_target(next_state, next_action)\n",
    "        curr_return = reward + gamma * next_value * masks\n",
    "        curr_return = curr_return.to(device).detach()\n",
    "\n",
    "        # train critic\n",
    "        values = self.critic(state, action)\n",
    "        critic_loss_element_wise = (values - curr_return).pow(2)\n",
    "\n",
    "        return critic_loss_element_wise\n",
    "    \n",
    "    def _target_soft_update(self):\n",
    "        \"\"\"Soft-update: target = tau*local + (1-tau)*target.\"\"\"\n",
    "        tau = self.tau\n",
    "        \n",
    "        for t_param, l_param in zip(\n",
    "            self.actor_target.parameters(), self.actor.parameters()\n",
    "        ):\n",
    "            t_param.data.copy_(tau * l_param.data + (1.0 - tau) * t_param.data)\n",
    "            \n",
    "        for t_param, l_param in zip(\n",
    "            self.critic_target.parameters(), self.critic.parameters()\n",
    "        ):\n",
    "            t_param.data.copy_(tau * l_param.data + (1.0 - tau) * t_param.data)\n",
    "    \n",
    "    def _get_n_step_info_from_demo(\n",
    "        self, demo: List, n_step: int\n",
    "    ) -> Tuple[List, List]:\n",
    "        \"\"\"Return 1 step and n step demos.\"\"\"\n",
    "        demos_1_step = list()\n",
    "        demos_n_step = list()\n",
    "        n_step_buffer: Deque = deque(maxlen=n_step)\n",
    "\n",
    "        for transition in demo:\n",
    "            n_step_buffer.append(transition)\n",
    "\n",
    "            if len(n_step_buffer) == n_step:\n",
    "                # add a single step transition\n",
    "                demos_1_step.append(n_step_buffer[0])\n",
    "\n",
    "                # add a multi step transition\n",
    "                curr_state, action = n_step_buffer[0][:2]\n",
    "                \n",
    "                # get n-step info\n",
    "                reward, next_state, done = n_step_buffer[-1][-3:]\n",
    "                for transition in reversed(list(n_step_buffer)[:-1]):\n",
    "                    r, n_o, d = transition[-3:]\n",
    "\n",
    "                    reward = r + self.gamma * reward * (1 - d)\n",
    "                    next_state, done = (n_o, d) if d else (next_state, done)\n",
    "                \n",
    "                transition = (curr_state, action, reward, next_state, done)\n",
    "                demos_n_step.append(transition)\n",
    "\n",
    "        return demos_1_step, demos_n_step\n",
    "    \n",
    "    def _plot(\n",
    "        self, \n",
    "        frame_idx: int, \n",
    "        scores: List[float], \n",
    "        actor_losses: List[float], \n",
    "        critic_losses: List[float], \n",
    "        n_demo: List[int],\n",
    "    ):\n",
    "        \"\"\"Plot the training progresses.\"\"\"\n",
    "        def subplot(loc: int, title: str, values: List[float]):\n",
    "            plt.subplot(loc)\n",
    "            plt.title(title)\n",
    "            plt.plot(values)\n",
    "                   \n",
    "        subplot_params = [\n",
    "            (141, f\"frame {frame_idx}. score: {np.mean(scores[-10:])}\", scores),\n",
    "            (142, \"actor_loss\", actor_losses),\n",
    "            (143, \"critic_loss\", critic_losses),\n",
    "            (144, \"the number of sampling demos\", n_demo),\n",
    "        ]\n",
    "        \n",
    "        clear_output(True)\n",
    "        plt.figure(figsize=(30, 5))            \n",
    "        for loc, title, values in subplot_params:\n",
    "            subplot(loc, title, values)\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Environment\n",
    "*ActionNormalizer* is an action wrapper class to normalize the action values ranged in (-1. 1). Thanks to this class, we can make the agent simply select action values within the zero centered range (-1, 1)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ActionNormalizer(gym.ActionWrapper):\n",
    "    \"\"\"Rescale and relocate the actions.\"\"\"\n",
    "\n",
    "    def action(self, action: np.ndarray) -> np.ndarray:\n",
    "        \"\"\"Change the range (-1, 1) to (low, high).\"\"\"\n",
    "        low = self.action_space.low\n",
    "        high = self.action_space.high\n",
    "\n",
    "        scale_factor = (high - low) / 2\n",
    "        reloc_factor = high - scale_factor\n",
    "\n",
    "        action = action * scale_factor + reloc_factor\n",
    "        action = np.clip(action, low, high)\n",
    "\n",
    "        return action\n",
    "\n",
    "    def reverse_action(self, action: np.ndarray) -> np.ndarray:\n",
    "        \"\"\"Change the range (low, high) to (-1, 1).\"\"\"\n",
    "        low = self.action_space.low\n",
    "        high = self.action_space.high\n",
    "\n",
    "        scale_factor = (high - low) / 2\n",
    "        reloc_factor = high - scale_factor\n",
    "\n",
    "        action = (action - reloc_factor) / scale_factor\n",
    "        action = np.clip(action, -1.0, 1.0)\n",
    "\n",
    "        return action"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can see [the code](https://github.com/openai/gym/blob/master/gym/envs/classic_control/pendulum.py) and [configurations](https://github.com/openai/gym/blob/cedecb35e3428985fd4efad738befeb75b9077f1/gym/envs/__init__.py#L81) of Pendulum-v0 from OpenAI's repository."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# environment\n",
    "env_id = \"Pendulum-v0\"\n",
    "env = gym.make(env_id)\n",
    "env = ActionNormalizer(env)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize\n",
    "We make the demonstration using the well-trained agent in advance. (The given demo.pkl is created transitions using *03.DDPG* agent.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "\n",
    "# load demo on replay memory\n",
    "demo_path = \"demo.pkl\"\n",
    "with open(demo_path, \"rb\") as f:\n",
    "    demo = pickle.load(f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda\n"
     ]
    }
   ],
   "source": [
    "# parameters\n",
    "num_frames = 50000\n",
    "memory_size = 100000\n",
    "batch_size = 128\n",
    "ou_noise_theta = 1.0\n",
    "ou_noise_sigma = 0.1\n",
    "initial_random_steps = 10000\n",
    "n_step = 3\n",
    "pretrain_step = 1000\n",
    "\n",
    "agent = DDPGfDAgent(\n",
    "    env, \n",
    "    memory_size, \n",
    "    batch_size,\n",
    "    ou_noise_theta,\n",
    "    ou_noise_sigma,\n",
    "    demo,\n",
    "    n_step=n_step,\n",
    "    pretrain_step=pretrain_step,\n",
    "    initial_random_steps=initial_random_steps,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 2160x360 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "agent.train(num_frames)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test\n",
    "Run the trained agent (1 episode)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "score:  -119.63754896934351\n"
     ]
    }
   ],
   "source": [
    "frames = agent.test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Render"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Define the Animation class */\n",
       "  function Animation(frames, img_id, slider_id, interval, loop_select_id){\n",
       "    this.img_id = img_id;\n",
       "    this.slider_id = slider_id;\n",
       "    this.loop_select_id = loop_select_id;\n",
       "    this.interval = interval;\n",
       "    this.current_frame = 0;\n",
       "    this.direction = 0;\n",
       "    this.timer = null;\n",
       "    this.frames = new Array(frames.length);\n",
       "\n",
       "    for (var i=0; i<frames.length; i++)\n",
       "    {\n",
       "     this.frames[i] = new Image();\n",
       "     this.frames[i].src = frames[i];\n",
       "    }\n",
       "    document.getElementById(this.slider_id).max = this.frames.length - 1;\n",
       "    this.set_frame(this.current_frame);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.get_loop_state = function(){\n",
       "    var button_group = document[this.loop_select_id].state;\n",
       "    for (var i = 0; i < button_group.length; i++) {\n",
       "        var button = button_group[i];\n",
       "        if (button.checked) {\n",
       "            return button.value;\n",
       "        }\n",
       "    }\n",
       "    return undefined;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.set_frame = function(frame){\n",
       "    this.current_frame = frame;\n",
       "    document.getElementById(this.img_id).src = this.frames[this.current_frame].src;\n",
       "    document.getElementById(this.slider_id).value = this.current_frame;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.next_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.min(this.frames.length - 1, this.current_frame + 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.previous_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.max(0, this.current_frame - 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.first_frame = function()\n",
       "  {\n",
       "    this.set_frame(0);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.last_frame = function()\n",
       "  {\n",
       "    this.set_frame(this.frames.length - 1);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.slower = function()\n",
       "  {\n",
       "    this.interval /= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.faster = function()\n",
       "  {\n",
       "    this.interval *= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_forward = function()\n",
       "  {\n",
       "    this.current_frame += 1;\n",
       "    if(this.current_frame < this.frames.length){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.first_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.last_frame();\n",
       "        this.reverse_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.last_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_reverse = function()\n",
       "  {\n",
       "    this.current_frame -= 1;\n",
       "    if(this.current_frame >= 0){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.last_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.first_frame();\n",
       "        this.play_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.first_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.pause_animation = function()\n",
       "  {\n",
       "    this.direction = 0;\n",
       "    if (this.timer){\n",
       "      clearInterval(this.timer);\n",
       "      this.timer = null;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.play_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = 1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_forward();}, this.interval);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.reverse_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = -1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_reverse();}, this.interval);\n",
       "  }\n",
       "</script>\n",
       "\n",
       "<div class=\"animation\" align=\"center\">\n",
       "    <img id=\"_anim_imgFAKHABPRBRVHVVHV\">\n",
       "    <br>\n",
       "    <input id=\"_anim_sliderFAKHABPRBRVHVVHV\" type=\"range\" style=\"width:350px\" name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\" onchange=\"animFAKHABPRBRVHVVHV.set_frame(parseInt(this.value));\"></input>\n",
       "    <br>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.slower()\">&#8211;</button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.first_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.previous_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.reverse_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.pause_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.play_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.next_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.last_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animFAKHABPRBRVHVVHV.faster()\">+</button>\n",
       "  <form action=\"#n\" name=\"_anim_loop_selectFAKHABPRBRVHVVHV\" class=\"anim_control\">\n",
       "    <input type=\"radio\" name=\"state\" value=\"once\" > Once </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"loop\" checked> Loop </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"reflect\" > Reflect </input>\n",
       "  </form>\n",
       "</div>\n",
       "\n",
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Instantiate the Animation class. */\n",
       "  /* The IDs given should match those used in the template above. */\n",
       "  (function() {\n",
       "    var img_id = \"_anim_imgFAKHABPRBRVHVVHV\";\n",
       "    var slider_id = \"_anim_sliderFAKHABPRBRVHVVHV\";\n",
       "    var loop_select_id = \"_anim_loop_selectFAKHABPRBRVHVVHV\";\n",
       "    var frames = new Array(0);\n",
       "    \n",
       "  frames[0] = \"\"\n",
       "  frames[1] = \"\"\n",
       "  frames[2] = \"\"\n",
       "  frames[3] = \"\"\n",
       "  frames[4] = \"\"\n",
       "  frames[5] = \"\"\n",
       "  frames[6] = \"\"\n",
       "  frames[7] = \"\"\n",
       "  frames[8] = \"\"\n",
       "  frames[9] = \"\"\n",
       "  frames[10] = \"\"\n",
       "  frames[11] = \"\"\n",
       "  frames[12] = \"\"\n",
       "  frames[13] = \"\"\n",
       "  frames[14] = \"\"\n",
       "  frames[15] = \"\"\n",
       "  frames[16] = \"\"\n",
       "  frames[17] = \"\"\n",
       "  frames[18] = \"\"\n",
       "  frames[19] = \"\"\n",
       "  frames[20] = \"\"\n",
       "  frames[21] = \"\"\n",
       "  frames[22] = \"\"\n",
       "  frames[23] = \"\"\n",
       "  frames[24] = \"\"\n",
       "  frames[25] = \"\"\n",
       "  frames[26] = \"\"\n",
       "  frames[27] = \"\"\n",
       "  frames[28] = \"\"\n",
       "  frames[29] = \"\"\n",
       "  frames[30] = \"\"\n",
       "  frames[31] = \"\"\n",
       "  frames[32] = \"\"\n",
       "  frames[33] = \"\"\n",
       "  frames[34] = \"\"\n",
       "  frames[35] = \"\"\n",
       "  frames[36] = \"\"\n",
       "  frames[37] = \"\"\n",
       "  frames[38] = \"\"\n",
       "  frames[39] = \"\"\n",
       "  frames[40] = \"\"\n",
       "  frames[41] = \"\"\n",
       "  frames[42] = \"\"\n",
       "  frames[43] = \"\"\n",
       "  frames[44] = \"\"\n",
       "  frames[45] = \"\"\n",
       "  frames[46] = \"\"\n",
       "  frames[47] = \"\"\n",
       "  frames[48] = \"\"\n",
       "  frames[49] = \"\"\n",
       "  frames[50] = \"\"\n",
       "  frames[51] = \"\"\n",
       "  frames[52] = \"\"\n",
       "  frames[53] = \"\"\n",
       "  frames[54] = \"\"\n",
       "  frames[55] = \"\"\n",
       "  frames[56] = \"\"\n",
       "  frames[57] = \"\"\n",
       "  frames[58] = \"\"\n",
       "  frames[59] = \"\"\n",
       "  frames[60] = \"\"\n",
       "  frames[61] = \"\"\n",
       "  frames[62] = \"\"\n",
       "  frames[63] = \"\"\n",
       "  frames[64] = \"\"\n",
       "  frames[65] = \"\"\n",
       "  frames[66] = \"\"\n",
       "  frames[67] = \"\"\n",
       "  frames[68] = \"\"\n",
       "  frames[69] = \"\"\n",
       "  frames[70] = \"\"\n",
       "  frames[71] = \"\"\n",
       "  frames[72] = \"\"\n",
       "  frames[73] = \"\"\n",
       "  frames[74] = \"\"\n",
       "  frames[75] = \"\"\n",
       "  frames[76] = \"\"\n",
       "  frames[77] = \"\"\n",
       "  frames[78] = \"\"\n",
       "  frames[79] = \"\"\n",
       "  frames[80] = \"\"\n",
       "  frames[81] = \"\"\n",
       "  frames[82] = \"\"\n",
       "  frames[83] = \"\"\n",
       "  frames[84] = \"\"\n",
       "  frames[85] = \"\"\n",
       "  frames[86] = \"\"\n",
       "  frames[87] = \"\"\n",
       "  frames[88] = \"\"\n",
       "  frames[89] = \"\"\n",
       "  frames[90] = \"\"\n",
       "  frames[91] = \"\"\n",
       "  frames[92] = \"\"\n",
       "  frames[93] = \"\"\n",
       "  frames[94] = \"\"\n",
       "  frames[95] = \"\"\n",
       "  frames[96] = \"\"\n",
       "  frames[97] = \"\"\n",
       "  frames[98] = \"\"\n",
       "  frames[99] = \"\"\n",
       "  frames[100] = \"\"\n",
       "  frames[101] = \"\"\n",
       "  frames[102] = \"\"\n",
       "  frames[103] = \"\"\n",
       "  frames[104] = \"\"\n",
       "  frames[105] = \"\"\n",
       "  frames[106] = \"\"\n",
       "  frames[107] = \"\"\n",
       "  frames[108] = \"\"\n",
       "  frames[109] = \"\"\n",
       "  frames[110] = \"\"\n",
       "  frames[111] = \"\"\n",
       "  frames[112] = \"\"\n",
       "  frames[113] = \"\"\n",
       "  frames[114] = \"\"\n",
       "  frames[115] = \"\"\n",
       "  frames[116] = \"\"\n",
       "  frames[117] = \"\"\n",
       "  frames[118] = \"\"\n",
       "  frames[119] = \"\"\n",
       "  frames[120] = \"\"\n",
       "  frames[121] = \"\"\n",
       "  frames[122] = \"\"\n",
       "  frames[123] = \"\"\n",
       "  frames[124] = \"\"\n",
       "  frames[125] = \"\"\n",
       "  frames[126] = \"\"\n",
       "  frames[127] = \"\"\n",
       "  frames[128] = \"\"\n",
       "  frames[129] = \"\"\n",
       "  frames[130] = \"\"\n",
       "  frames[131] = \"\"\n",
       "  frames[132] = \"\"\n",
       "  frames[133] = \"\"\n",
       "  frames[134] = \"\"\n",
       "  frames[135] = \"\"\n",
       "  frames[136] = \"\"\n",
       "  frames[137] = \"\"\n",
       "  frames[138] = \"\"\n",
       "  frames[139] = \"\"\n",
       "  frames[140] = \"\"\n",
       "  frames[141] = \"\"\n",
       "  frames[142] = \"\"\n",
       "  frames[143] = \"\"\n",
       "  frames[144] = \"\"\n",
       "  frames[145] = \"\"\n",
       "  frames[146] = \"\"\n",
       "  frames[147] = \"\"\n",
       "  frames[148] = \"\"\n",
       "  frames[149] = \"\"\n",
       "  frames[150] = \"\"\n",
       "  frames[151] = \"\"\n",
       "  frames[152] = \"\"\n",
       "  frames[153] = \"\"\n",
       "  frames[154] = \"\"\n",
       "  frames[155] = \"\"\n",
       "  frames[156] = \"\"\n",
       "  frames[157] = \"\"\n",
       "  frames[158] = \"\"\n",
       "  frames[159] = \"\"\n",
       "  frames[160] = \"\"\n",
       "  frames[161] = \"\"\n",
       "  frames[162] = \"\"\n",
       "  frames[163] = \"\"\n",
       "  frames[164] = \"\"\n",
       "  frames[165] = \"\"\n",
       "  frames[166] = \"\"\n",
       "  frames[167] = \"\"\n",
       "  frames[168] = \"\"\n",
       "  frames[169] = \"\"\n",
       "  frames[170] = \"\"\n",
       "  frames[171] = \"\"\n",
       "  frames[172] = \"\"\n",
       "  frames[173] = \"\"\n",
       "  frames[174] = \"\"\n",
       "  frames[175] = \"\"\n",
       "  frames[176] = \"\"\n",
       "  frames[177] = \"\"\n",
       "  frames[178] = \"\"\n",
       "  frames[179] = \"\"\n",
       "  frames[180] = \"\"\n",
       "  frames[181] = \"\"\n",
       "  frames[182] = \"\"\n",
       "  frames[183] = \"\"\n",
       "  frames[184] = \"\"\n",
       "  frames[185] = \"\"\n",
       "  frames[186] = \"\"\n",
       "  frames[187] = \"\"\n",
       "  frames[188] = \"\"\n",
       "  frames[189] = \"\"\n",
       "  frames[190] = \"\"\n",
       "  frames[191] = \"\"\n",
       "  frames[192] = \"\"\n",
       "  frames[193] = \"\"\n",
       "  frames[194] = \"\"\n",
       "  frames[195] = \"\"\n",
       "  frames[196] = \"\"\n",
       "  frames[197] = \"\"\n",
       "  frames[198] = \"\"\n",
       "  frames[199] = \"\"\n",
       "\n",
       "\n",
       "    /* set a timeout to make sure all the above elements are created before\n",
       "       the object is initialized. */\n",
       "    setTimeout(function() {\n",
       "        animFAKHABPRBRVHVVHV = new Animation(frames, img_id, slider_id, 50, loop_select_id);\n",
       "    }, 0);\n",
       "  })()\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Imports specifically so we can render outputs in Colab.\n",
    "from matplotlib import animation\n",
    "from JSAnimation.IPython_display import display_animation\n",
    "from IPython.display import display\n",
    "\n",
    "\n",
    "def display_frames_as_gif(frames):\n",
    "    \"\"\"Displays a list of frames as a gif, with controls.\"\"\"\n",
    "    patch = plt.imshow(frames[0])\n",
    "    plt.axis('off')\n",
    "\n",
    "    def animate(i):\n",
    "        patch.set_data(frames[i])\n",
    "\n",
    "    anim = animation.FuncAnimation(\n",
    "        plt.gcf(), animate, frames = len(frames), interval=50\n",
    "    )\n",
    "    display(display_animation(anim, default_mode='loop'))\n",
    "    \n",
    "        \n",
    "# display \n",
    "display_frames_as_gif(frames)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
